package com.zero.flutter_gromore_ads;

import android.app.Activity;
import android.app.Instrumentation;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;

import androidx.annotation.NonNull;

import com.bytedance.mtesttools.api.TTMediationTestTool;
import com.bytedance.sdk.openadsdk.AdSlot;
import com.bytedance.sdk.openadsdk.TTAdConfig;
import com.bytedance.sdk.openadsdk.TTAdSdk;
import com.bytedance.sdk.openadsdk.TTCustomController;
import com.bytedance.sdk.openadsdk.mediation.IMediationManager;
import com.bytedance.sdk.openadsdk.mediation.IMediationPreloadRequestInfo;
import com.bytedance.sdk.openadsdk.mediation.MediationConstant;
import com.bytedance.sdk.openadsdk.mediation.MediationPreloadRequestInfo;
import com.bytedance.sdk.openadsdk.mediation.ad.MediationAdSlot;
import com.bytedance.sdk.openadsdk.mediation.init.MediationConfig;
import com.bytedance.sdk.openadsdk.mediation.init.MediationPrivacyConfig;
import com.zero.flutter_gromore_ads.load.FeedAdLoad;
import com.zero.flutter_gromore_ads.load.FeedAdManager;
import com.zero.flutter_gromore_ads.load.SplashAdLoad;
import com.zero.flutter_gromore_ads.page.InterstitialPage;
import com.zero.flutter_gromore_ads.page.NativeViewFactory;
import com.zero.flutter_gromore_ads.page.RewardVideoPage;
import com.zero.flutter_gromore_ads.utils.FileUtils;
import com.zero.flutter_gromore_ads.utils.InstrumentationProxy;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import io.flutter.BuildConfig;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;

/// 插件代理
public class PluginDelegate implements MethodChannel.MethodCallHandler, EventChannel.StreamHandler {
    private final String TAG = PluginDelegate.class.getSimpleName();
    // Flutter 插件绑定对象
    public FlutterPlugin.FlutterPluginBinding bind;
    // 当前 Activity
    public Activity activity;
    // 返回通道
    private MethodChannel.Result result;
    // 事件通道
    private EventChannel.EventSink eventSink;
    // 插件代理对象
    private static PluginDelegate _instance;

    public static PluginDelegate getInstance() {
        return _instance;
    }

    // Banner View
    public static final String KEY_BANNER_VIEW = "flutter_gromore_ads_banner";
    // Feed View
    public static final String KEY_FEED_VIEW = "flutter_gromore_ads_feed";
    // Draw View
    public static final String KEY_DRAW_FEED_VIEW = "flutter_gromore_ads_draw_feed";
    // 广告参数
    public static final String KEY_POSID = "posId";
    // logo 参数
    public static final String KEY_LOGO = "logo";
    // timeout 参数
    public static final String KEY_TIMEOUT = "timeout";
    // 预加载
    public static final String PRELOAD = "preload";
    // 是否初始化
    public static boolean adInit = false;
    // 初始化配置
    private boolean isLimitPersonalAds = false;
    private boolean isLocation = true;
    private boolean isPhoneState = true;
    private boolean isAlist = true;
    private boolean isAndroidId = true;
    private boolean isOaid = true;
    // 开屏广告加载对象
    public SplashAdLoad splashAdLoad;

    /**
     * 插件代理构造函数构造函数
     *
     * @param activity      Activity
     * @param pluginBinding FlutterPluginBinding
     */
    public PluginDelegate(Activity activity, FlutterPlugin.FlutterPluginBinding pluginBinding) {
        this.activity = activity;
        this.bind = pluginBinding;
        _instance = this;
    }

    /**
     * 方法通道调用
     *
     * @param call   方法调用对象
     * @param result 回调结果对象
     */
    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
        String method = call.method;
        Log.d(TAG, "MethodChannel onMethodCall method:" + method + " arguments:" + call.arguments);
        if ("requestPermissionIfNecessary".equals(method)) {
            requestPermissionIfNecessary(call, result);
        } else if ("initAd".equals(method)) {
            initAd(call, result);
        } else if ("preload".equals(method)) {
            preload(call, result);
        } else if ("showSplashAd".equals(method)) {
            showSplashAd(call, result);
        } else if ("showInterstitialAd".equals(method)) {
            showInterstitialAd(call, result);
        } else if ("showRewardVideoAd".equals(method)) {
            showRewardVideoAd(call, result);
        } else if ("loadFeedAd".equals(method)) {
            loadFeedAd(call, result);
        } else if ("clearFeedAd".equals(method)) {
            clearFeedAd(call, result);
        } else if ("launchTestTools".equals(method)) {
            launchTestTools(call, result);
        } else if ("blockQuickApp".equals(method)) {
            blockQuickApp(call, result);
        } else {
            result.notImplemented();
        }
    }

    /**
     * 建立事件通道监听
     *
     * @param arguments 参数
     * @param events    事件回调对象
     */
    @Override
    public void onListen(Object arguments, EventChannel.EventSink events) {
        Log.d(TAG, "EventChannel onListen arguments:" + arguments);
        eventSink = events;
    }

    /**
     * 取消事件通道监听
     *
     * @param arguments 参数
     */
    @Override
    public void onCancel(Object arguments) {
        Log.d(TAG, "EventChannel onCancel");
        eventSink = null;
    }

    /**
     * 添加事件
     *
     * @param event 事件
     */
    public void addEvent(Object event) {
        if (eventSink != null) {
            Log.d(TAG, "EventChannel addEvent event:" + event.toString());
            eventSink.success(event);
        }
    }

    /**
     * 展示 Banner 广告
     */
    public void registerBannerView() {
        bind.getPlatformViewRegistry()
                .registerViewFactory(KEY_BANNER_VIEW, new NativeViewFactory(KEY_BANNER_VIEW, this));
    }

    /**
     * 展示 Feed 信息流广告
     */
    public void registerFeedView() {
        bind.getPlatformViewRegistry()
                .registerViewFactory(KEY_FEED_VIEW, new NativeViewFactory(KEY_FEED_VIEW, this));
    }

    /**
     * 展示 Draw 信息流广告
     */
    public void registerDrawFeedView() {
        bind.getPlatformViewRegistry()
                .registerViewFactory(KEY_DRAW_FEED_VIEW, new NativeViewFactory(KEY_DRAW_FEED_VIEW, this));
    }

    /**
     * 请求权限
     *
     * @param call   MethodCall
     * @param result Result
     */
    public void requestPermissionIfNecessary(MethodCall call, MethodChannel.Result result) {
        TTAdSdk.getMediationManager().requestPermissionIfNecessary(activity);
        result.success(true);
    }

    /**
     * 初始化广告
     *
     * @param call   MethodCall
     * @param result Result
     */
    public void initAd(MethodCall call, final MethodChannel.Result result) {
        if (adInit) {
            result.success(TTAdSdk.isSdkReady());
            Log.w(TAG, "SDK 已初始化过");
            return;
        }
        String appId = call.argument("appId");
        String config = call.argument("config");
        Boolean useMediation = call.argument("useMediation");
        int themeStatus = call.argument("themeStatus");
        int limitPersonalAds = call.argument("limitPersonalAds");
        isLimitPersonalAds = limitPersonalAds == 0;
        isLocation = call.argument("isLocation");
        isPhoneState = call.argument("isPhoneState");
        isAlist = call.argument("isAlist");
        isAndroidId = call.argument("isAndroidId");
        isOaid = call.argument("isOaid");
        // 判断是否为空
        if (TextUtils.isEmpty(appId)) {
            Log.e(TAG, "appId is null");
            result.success(false);
            return;
        }

        // 构建基础配置
        TTAdConfig.Builder configBuilder = new TTAdConfig.Builder()
                .appId(appId)
                .useMediation(useMediation)
                .debug(BuildConfig.DEBUG)
                .supportMultiProcess(false)
                .themeStatus(themeStatus);
        // 离线配置
        JSONObject localConfigJson = null;
        if (!TextUtils.isEmpty(config)) {
            String localConfigStr = FileUtils.getJson(config, activity);
            try {
                localConfigJson = new JSONObject(localConfigStr);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        // 构建配置
        TTAdConfig gmPangleOption;
        if (localConfigJson != null) {
            gmPangleOption = configBuilder
                    .customController(getTTCustomController())
                    .setMediationConfig(new MediationConfig.Builder()
                            .setCustomLocalConfig(localConfigJson)
                            .build()).build();
        } else {
            gmPangleOption = configBuilder
                    .customController(getTTCustomController())
                    .build();
        }
        // 初始化 SDK
        TTAdSdk.init(activity.getApplicationContext(), gmPangleOption);
        TTAdSdk.start(new TTAdSdk.Callback() {
            @Override
            public void success() {
                result.success(TTAdSdk.isSdkReady());
                adInit = true;
            }

            @Override
            public void fail(int i, String s) {
                result.success(false);
                Log.e(TAG, "TTAdSdk init start Error code:" + i + " msg:" + s);
                adInit = false;
            }
        });
    }

    /**
     * 预加载
     *
     * @param call
     * @param result
     */
    public void preload(MethodCall call, final MethodChannel.Result result) {
        // 判断是否为空
        if (activity == null) {
            Log.e(TAG, "Activity is null");
            result.success(false);
            return;
        }
        // 判断是否初始化成功
        if (!adInit) {
            Log.e(TAG, "SDK is not initialized successfully");
            result.success(false);
            return;
        }

        List<String> rewardPosids = call.argument("rewardPosids");
        List<String> insertPosids = call.argument("insertPosids");
        int concurrent = call.argument("concurrent");
        int interval = call.argument("interval");
        List<IMediationPreloadRequestInfo> requestInfoList = new ArrayList<>();
        if (rewardPosids != null && !rewardPosids.isEmpty()) {
            String customData = call.argument("customData");
            String userId = call.argument("userId");
            int orientation = call.argument("orientation");
            // 激励视频
            AdSlot adSlotReward = new AdSlot.Builder()
                    .setUserID(userId)//tag_id
                    .setOrientation(orientation)
                    .setMediationAdSlot(new MediationAdSlot
                            .Builder()
                            .setExtraObject(MediationConstant.CUSTOM_DATA_KEY_GROMORE_EXTRA, customData)
                            .build())
                    .build();
            IMediationPreloadRequestInfo preloadReward = new MediationPreloadRequestInfo(AdSlot.TYPE_REWARD_VIDEO, adSlotReward, rewardPosids);
            requestInfoList.add(preloadReward);
        }
        if (insertPosids != null && !insertPosids.isEmpty()) {
            // 插屏
            AdSlot adSlotInsert = new AdSlot.Builder().build();
            IMediationPreloadRequestInfo preloadInsert = new MediationPreloadRequestInfo(AdSlot.TYPE_FULL_SCREEN_VIDEO, adSlotInsert, insertPosids);
            requestInfoList.add(preloadInsert);
        }
        // 判断是否为空
        if (requestInfoList.isEmpty()) {
            result.success(false);
        } else {
            IMediationManager mediationManager = TTAdSdk.getMediationManager();
            if (mediationManager != null) {
                mediationManager.preload(activity, requestInfoList, concurrent, interval);
                result.success(true);
            } else {
                Log.e(TAG, "MediationManager is null");
                result.success(false);
            }
        }

    }


    private TTCustomController getTTCustomController() {
        return new TTCustomController() {

            @Override
            public boolean isCanUseLocation() {
                // 是否允许SDK主动使用ACCESS_FINE_LOCATION权限
                return isLocation;
            }

            @Override
            public boolean isCanUsePhoneState() {
                // 是否允许SDK主动使用ACCESS_PHONE_STATE权限
                return isPhoneState;
            }

            @Override
            public boolean isCanUseWifiState() {
                // 是否允许SDK主动使用ACCESS_WIFI_STATE权限
                return super.isCanUseWifiState();
            }

            @Override
            public String getMacAddress() {
                return super.getMacAddress();
            }

            @Override
            public boolean isCanUseWriteExternal() {
                // 是否允许SDK主动使用WRITE_EXTERNAL_STORAGE权限
                return super.isCanUseWriteExternal();
            }

            @Override
            public String getDevOaid() {
                return super.getDevOaid();
            }

            @Override
            public boolean isCanUseAndroidId() {
                // 是否能获取android ID
                return isAndroidId;
            }

            @Override
            public String getAndroidId() {
                return super.getAndroidId();
            }

            @Override
            public boolean alist() {
                // 是否允许sdk上报手机app安装列表
                return isAlist;
            }

            @Override
            public MediationPrivacyConfig getMediationPrivacyConfig() {
                return new MediationPrivacyConfig() {

                    @Override
                    public boolean isLimitPersonalAds() {
                        return !isLimitPersonalAds;
                    }

                    @Override
                    public boolean isProgrammaticRecommend() {
                        return isLimitPersonalAds;
                    }

                    @Override
                    public boolean isCanUseOaid() {
                        // 是否允许SDK主动使用OAID
                        return isOaid;
                    }
                };
            }

            @Override
            public boolean isCanUsePermissionRecordAudio() {
                return super.isCanUsePermissionRecordAudio();
            }
        };
    }

    /**
     * 显示开屏广告
     *
     * @param call   MethodCall
     * @param result Result
     */
    public void showSplashAd(MethodCall call, MethodChannel.Result result) {
        if (splashAdLoad != null && splashAdLoad.isDisplay) {
            result.success(false);
            Log.e(TAG, "showSplashAd 广告展示中，无法再次展示");
            return;
        }
        boolean preload = call.argument(PRELOAD);
        // 如果是预加载的情况下，已经加载完毕则进行展示
        if (splashAdLoad != null && splashAdLoad.isLoaded && preload) {
            splashAdLoad.goActivity();
        } else {
            // 加载广告并展示，如果非预加载的情况下
            splashAdLoad = new SplashAdLoad();
            splashAdLoad.showAd(activity, call);
        }
        result.success(true);
    }

    /**
     * 显示插屏广告
     *
     * @param call   MethodCall
     * @param result Result
     */
    public void showInterstitialAd(MethodCall call, MethodChannel.Result result) {
        InterstitialPage adPage = new InterstitialPage();
        adPage.showAd(activity, call);
        result.success(true);
    }

    /**
     * 显示激励视频广告
     *
     * @param call   MethodCall
     * @param result Result
     */
    public void showRewardVideoAd(MethodCall call, MethodChannel.Result result) {
        RewardVideoPage adPage = new RewardVideoPage();
        adPage.showAd(activity, call);
        result.success(true);
    }

    /**
     * 加载信息流广告列表
     *
     * @param call   MethodCall
     * @param result Result
     */
    public void loadFeedAd(MethodCall call, MethodChannel.Result result) {
        FeedAdLoad feedAd = new FeedAdLoad();
        feedAd.loadFeedAdList(activity, call, result);
    }

    /**
     * 删除信息流广告列表
     *
     * @param call   MethodCall
     * @param result Result
     */
    public void clearFeedAd(MethodCall call, MethodChannel.Result result) {
        List<Integer> adList = call.argument("list");
        if (adList != null) {
            for (int ad : adList) {
                FeedAdManager.getInstance().removeAd(ad);
                FeedAdManager.getInstance().removeDrawAd(ad);
            }
        }
        result.success(true);
    }

    /**
     * 启动测试工具
     *
     * @param call   MethodCall
     * @param result Result
     */
    public void launchTestTools(MethodCall call, MethodChannel.Result result) {
        // if (BuildConfig.DEBUG) {
        TTMediationTestTool.launchTestTools(activity, new TTMediationTestTool.ImageCallBack() {
            @Override
            public void loadImage(ImageView imageView, String s) {

            }
        });
        // }
        result.success(true);
    }

    /**
     * 拦截快应用
     *
     * @param call   MethodCall
     * @param result Result
     */
    public void blockQuickApp(MethodCall call, MethodChannel.Result result) {
        hookStartActivity();
        result.success(true);
    }


    /**
     * Hook Activity 的 startActivity 方法
     * 拦截快应用
     */
    public static void hookStartActivity() {
        try {
            // 获取ActivityThread类
            Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            // 获取ActivityThread类中的静态变量sCurrentActivityThread
            Field currentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
            currentActivityThreadField.setAccessible(true);
            // 获取sCurrentActivityThread字段的值，即ActivityThread的对象
            Object currentActivityThread = currentActivityThreadField.get(null);
            // 获取ActivityThread的mInstrumentation字段
            Field mInstrumentationField = activityThreadClass.getDeclaredField("mInstrumentation");
            mInstrumentationField.setAccessible(true);
            // 获取mInstrumentation对象
            Instrumentation instrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread);
            // 创建Instrumentation的代理对象
            InstrumentationProxy instrumentationProxy = new InstrumentationProxy(instrumentation);
            // 用InstrumentationProxy替换ActivityThread中的Instrumentation
            mInstrumentationField.set(currentActivityThread, instrumentationProxy);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }

}
